#target illustrator

#include "csv_reader.jsx"

// 全局配置
var CONFIG = {
    OBJECTS_PER_ROW: 6,         // 每行对象数量
    
    // --- 间距倍数配置 ---
    SPACING_MULTIPLIER_HORI: 1.05, // 左右间距倍数 (0.75 意味着重叠 25%)
    SPACING_MULTIPLIER_VERT: 1.05, // 上下间距倍数 (0.85 意味着重叠 15%)
    // -------------------
    
    SCLAE_MULTIPLIER_NUM: 1150,     // 数字部分的参考宽度
    SCLAE_MULTIPLIER_TXT: 992,      // 文字部分的参考宽度
    // MARGIN_X: 50,               // 边距已被移除，因为起始位置基于模板对象
    // MARGIN_Y: 50                // 边距已被移除，因为起始位置基于模板对象
};

// 辅助函数：尝试从选中对象中找到最合适的尺寸计算对象
function findBoundaryItem(item) {
    if (!item) return null;

    if (item.typename === "PathItem" || item.typename === "CompoundPathItem") {
        return item;
    }

    if (item.typename === "GroupItem" || item.typename === "Layer") {
        for (var i = 0; i < item.pageItems.length; i++) {
            var found = findBoundaryItem(item.pageItems[i]);
            if (found && (found.typename === "PathItem" || found.typename === "CompoundPathItem")) {
                if (item.clipped && found.clipping) {
                    return found;
                }
                return found;
            }
        }
    }
    
    return item; 
}

// 获取中心点 (保持不变)
function getCenter(item) {
    var bounds = item.geometricBounds;
    return [
        (bounds[0] + bounds[2]) / 2,  // centerX
        (bounds[1] + bounds[3]) / 2    // centerY
    ];
}


function replaceAndCopyObjects(data) {
    var doc = app.activeDocument;
    
    var selectedItems = doc.selection;
    
    // 1. 输入验证
    if (selectedItems.length < 2) {
        alert("请按顺序至少选中两个对象：\n1. 数字文本（内容参考）\n2. 文字文本（内容参考）\n3. 裁片（位置/尺寸参考）");
        return;
    }
    
    // 2. 将选中的对象复制到普通数组 baseItems 中，用于替换和复制时的引用
    var baseItems = []; 
    for (var i = 0; i < selectedItems.length; i++) {
        baseItems.push(selectedItems[i]);
    }
    
    // 3. 获取基准对象（裁片）
    var baseObject
    if (baseItems.length < 3)
        baseObject = baseItems[1]; 
    else 
        baseObject = baseItems[2]; 
        
    // 4. 提取路径对象以准确计算尺寸
    var boundaryItem = findBoundaryItem(baseObject);
    if (!boundaryItem) {
        boundaryItem = baseObject;
    }

    // 5. 计算尺寸和间距
    var bounds = boundaryItem.geometricBounds; 
    var objectWidth = bounds[2] - bounds[0];   
    var objectHeight = bounds[1] - bounds[3];  
    
    var horizontalSpacing = objectWidth * CONFIG.SPACING_MULTIPLIER_HORI;
    var verticalSpacing = objectHeight * CONFIG.SPACING_MULTIPLIER_VERT;
    
    // *** 关键修正：将起始位置 (i=0 的位置) 设置为裁片模板的中心点 ***
    var baseObjectCenter = getCenter(baseObject); 
    var startX = baseObjectCenter[0]; 
    var startY = baseObjectCenter[1];
    
    var groupCount = 0; 
    
    // 6. 替换/复制循环
    for (var i = 0; i < data.length; i++) {
        if (data[i][0] == '') break;
        
        var row = Math.floor(i / CONFIG.OBJECTS_PER_ROW);
        var col = i % CONFIG.OBJECTS_PER_ROW;
        
        // 计算目标位置（中心点）
        var targetX = startX + col * horizontalSpacing;
        var targetY = startY - row * verticalSpacing;
        
        var result;
        
        if (i === 0) {
            // 处理第一个数据，直接替换模板内容
            // 由于 startX/startY 已经是 baseObject 的中心，replaceOnlyAtPosition 中的移动逻辑将被跳过
            // 但仍需调用它来替换内容和编组
            result = replaceOnlyAtPosition(baseItems, data[i], targetX, targetY);
        } else {
            // 处理后续数据，复制并替换内容
            result = copyAndReplaceAtPosition(baseItems, data[i], targetX, targetY);
        }
        
        if (result && result.length > 0) {
            groupCount++;
        }
    }
    
    alert("处理完成！共处理了 " + data.length + " 个对象，创建了 " + groupCount + " 个编组");
}


// --- 替换内容和移动 (修正移动逻辑，使其在 deltaX/Y=0 时不移动) ---
function replaceOnlyAtPosition(baseItems, contents, targetX, targetY) {
    var doc = app.activeDocument;
    var firstItem = baseItems[0];   
    var secondItem = baseItems[1];  
    var thirdItem = baseItems.length < 3 ? baseItems[1] : baseItems[2]; // 底纹对象
    
    // 1. 替换内容
    if (contents[0]) replaceTextContent(firstItem, contents[0], 'NUM');
    if (baseItems.length >= 3 && contents[1]) replaceTextContent(secondItem, contents[1], 'TXT');
    
    // 2. 移动整个模板（如果 targetX/Y 与当前位置不一致）
    // 注意：由于 startX/startY 设置为 baseObject 中心，i=0 时 deltaX/Y 应为 0。
    var targetCenter = [targetX, targetY];
    var currentCenter = getCenter(thirdItem);
    var deltaX = targetCenter[0] - currentCenter[0];
    var deltaY = targetCenter[1] - currentCenter[1];
    
    if (Math.abs(deltaX) > 0.01 || Math.abs(deltaY) > 0.01) { // 使用微小误差判断，避免浮点数问题
        for (var i = 0; i < baseItems.length; i++) {
            baseItems[i].translate(deltaX, deltaY); 
        }
    }

    // 3. 将模板对象编组并修正图层顺序
    try {
        var newGroup = doc.groupItems.add();
        
        for (var i = baseItems.length - 1; i >= 0; i--) {
            baseItems[i].move(newGroup, ElementPlacement.PLACEATEND);
        }
        
        // 确保底纹在最底层
        if (thirdItem.parent === newGroup) {
            thirdItem.zOrder(ZOrderMethod.SENDTOBACK); 
        }

        return [newGroup];
    } catch (e) {
        return baseItems;
    }
}
// ---------------------------------------------


// --- 复制和替换函数 (保持不变) ---
function copyAndReplaceAtPosition(baseItems, contents, targetX, targetY) {
    var newObjects = []; 
    
    try {
        var firstItem = baseItems[0];   
        var secondItem = baseItems[1];  
        
        var thirdItemTemplate // 模板中的底纹对象
        if (baseItems.length < 3)
            thirdItemTemplate = baseItems[1]; 
        else 
            thirdItemTemplate = baseItems[2]; 

        // 复制底纹
        var newThirdItem = duplicateToPosition(thirdItemTemplate, targetX, targetY);
        if (!newThirdItem) return newObjects;
        newObjects.push(newThirdItem); 
        
        // 计算偏移量
        var originalCenter = getCenter(thirdItemTemplate);
        var newCenter = getCenter(newThirdItem);
        var offsetX = newCenter[0] - originalCenter[0];
        var offsetY = newCenter[1] - originalCenter[1];
        
        // 复制并替换文本
        var newFirstItem = duplicateWithOffset(firstItem, offsetX, offsetY);
        if (newFirstItem && contents[0]) {
            replaceTextContent(newFirstItem, contents[0],'NUM');
            newObjects.push(newFirstItem); 
        }
        
        if (baseItems.length >= 3){
            var newSecondItem = duplicateWithOffset(secondItem, offsetX, offsetY);
            if (newSecondItem && contents[1]) {
                replaceTextContent(newSecondItem, contents[1],'TXT');
                newObjects.push(newSecondItem); 
            }
        }
        
        // 编组并修正图层顺序
        if (newObjects.length > 0) {
            try {
                var doc = app.activeDocument;
                var newGroup = doc.groupItems.add();
                
                for (var i = newObjects.length - 1; i >= 0; i--) {
                    newObjects[i].move(newGroup, ElementPlacement.PLACEATEND);
                }
                
                // 确保底纹在最底层
                if (newThirdItem.parent === newGroup) {
                    newThirdItem.zOrder(ZOrderMethod.SENDTOBACK);
                }
                
                return [newGroup];
            } catch (e) {
                return newObjects;
            }
        }
        
    } catch (e) {
        alert("处理对象时出错: " + e.message);
    }
    
    return newObjects; 
}

function duplicateToPosition(item, targetX, targetY) {
    try {
        var newItem = item.duplicate();
        var center = getCenter(newItem);
        var deltaX = targetX - center[0];
        var deltaY = targetY - center[1];
        newItem.translate(deltaX, deltaY);
        return newItem;
    } catch (e) {
        alert("复制对象失败: " + e.message);
        return null;
    }
}

function duplicateWithOffset(item, offsetX, offsetY) {
    try {
        var newItem = item.duplicate();
        newItem.translate(offsetX, offsetY);
        return newItem;
    } catch (e) {
        alert("复制偏移对象失败: " + e.message);
        return null;
    }
}

function replaceTextContent(item, newText, textType) {
    try {
        
        if (item.typename == "TextFrame") {
            var originalFont = null;
            var originalSize = null;
            
            if (item.textRange && item.textRange.characterAttributes) {
                originalFont = item.textRange.characterAttributes.textFont;
                originalSize = item.textRange.characterAttributes.size;
            }
            
            item.contents = newText;
            
            if (item.textRange && item.textRange.characterAttributes) {
                if (originalFont) {
                    try {
                        item.textRange.characterAttributes.textFont = originalFont;
                    } catch (e) {
                        try {
                            item.textRange.characterAttributes.textFont = app.textFonts.getByName("Arial-BoldMT");
                        } catch (e2) {
                            if (app.textFonts.length > 0) {
                                item.textRange.characterAttributes.textFont = app.textFonts[0];
                            }
                        }
                    }
                }
                if (originalSize) {
                    item.textRange.characterAttributes.size = originalSize;
                }
            }

            var scaleFactor; 
            if (textType == 'NUM'){
                if (item.width > CONFIG.SCLAE_MULTIPLIER_NUM){
                    scaleFactor = CONFIG.SCLAE_MULTIPLIER_NUM / item.width; 
                    item.resize(scaleFactor * 100, 100);  
                }
            }else if (textType == 'TXT'){
                if (item.width > CONFIG.SCLAE_MULTIPLIER_TXT){
                    scaleFactor = CONFIG.SCLAE_MULTIPLIER_TXT / item.width; 
                    item.resize(scaleFactor * 100, 100);  
                }
            }
            return;
        }
        
        if (item.typename == "GroupItem") {
            for (var i = 0; i < item.pageItems.length; i++) {
                replaceTextContent(item.pageItems[i], newText, textType); 
            }
            return;
        }
        
        if (item.typename == "CompoundPathItem") {
            for (var i = 0; i < item.pathItems.length; i++) {
                replaceTextContent(item.pathItems[i], newText, textType); 
            }
        }
        
    } catch (e) {
        // 静默处理
    }
}

// 主执行函数
function main() {
    try {
        var data = readCSV();
        if (data && data.length > 0) {
            replaceAndCopyObjects(data);
        } else {
            alert("没有读取到有效的CSV数据");
        }
    } catch (e) {
        alert("脚本执行出错: " + e.message + "\n请确保 'csv_reader.jsx' 文件已正确引入。");
    }
}

// 执行主函数
main();